/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.buss.core.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;


/**
 *
 * @author gykl
 */
public class ZipUtil {

    /**
     * 压缩ZIP格式的字节数组，并以字节数组返回
     * @param bs
     * @return
     */
    public static byte[] zip(byte[] bs) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Deflater def = new Deflater();
        DeflaterOutputStream dos = new DeflaterOutputStream(bos, def);
        try {
            dos.write(bs);
            dos.finish();
            dos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] r = bos.toByteArray();
        return r;
    }

    /**
     * 压缩GZIP格式的字节数组，并以字节数组格式返回
     * @param bs
     * @return
     */
    public static byte[] gzip(byte[] bs) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            GZIPOutputStream dos = new GZIPOutputStream(bos);
            dos.write(bs);
            dos.finish();
            dos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] r = bos.toByteArray();
        return r;
    }

    /**
     * 压缩文件，并以目标文件保存
     * @param srcFile
     * @param destFile
     * @throws Exception
     */
    public static void zip(String srcFile, String destFile) throws Exception {
        OutputStream os = new FileOutputStream(destFile);
        zip(new File(srcFile), os);
        os.flush();
        os.close();
    }

    /**
     * 压缩文件到指定输出流
     * @param srcFile
     * @param destStream
     * @throws Exception
     */
    public static void zip(File srcFile, OutputStream destStream) throws Exception {
        List fileList = getSubFiles(srcFile);
        ZipOutputStream zos = new ZipOutputStream(destStream);
        ZipEntry ze = null;
        byte[] buf = new byte[1024];
        int readLen = 0;
        for (int i = 0; i < fileList.size(); ++i) {
            File f = (File) fileList.get(i);
            ze = new ZipEntry(getAbsFileName(srcFile, f));
            ze.setSize(f.length());
            ze.setTime(f.lastModified());
            Logger1.info("正在压缩:" + f.getPath(), ZipUtil.class);
            zos.putNextEntry(ze);
            if (f.isFile()) {
                InputStream is = new BufferedInputStream(new FileInputStream(f));
                while ((readLen = is.read(buf, 0, 1024)) != -1) {
                    zos.write(buf, 0, readLen);
                }
                is.close();
                zos.finish();
            }
        }
        zos.close();
        Logger1.info("压缩完毕!", ZipUtil.class);
    }

    /**
     * 批量压缩文件
     * @param srcFiles
     * @param destFile
     */
    public static void zipBatch(String[] srcFiles, String destFile) throws Exception {
        OutputStream os = new FileOutputStream(destFile);
        zipBatch(srcFiles, os);
        os.flush();
        os.close();
    }

    public static void zipBatch(String[] srcFiles, OutputStream destStream) throws Exception {
        File[] files = new File[srcFiles.length];
        for (int i = 0; i < srcFiles.length; ++i) {
            files[i] = new File(srcFiles[i]);
        }
        zipBatch(files, destStream);
    }

    public static void zipBatch(File[] srcFiles, OutputStream destStream) throws Exception {
        ZipOutputStream zos = new ZipOutputStream(destStream);
        for (int k = 0; k < srcFiles.length; ++k) {
            List fileList = getSubFiles(srcFiles[k]);
            ZipEntry ze = null;
            byte[] buf = new byte[1024];
            int readLen = 0;
            for (int i = 0; i < fileList.size(); ++i) {
                File f = (File) fileList.get(i);
                ze = new ZipEntry(getAbsFileName(srcFiles[k], f));
                ze.setSize(f.length());
                ze.setTime(f.lastModified());
                Logger1.info("正在压缩:" + f.getPath(), ZipUtil.class);
                zos.putNextEntry(ze);
                if (f.isFile()) {
                    InputStream is = new BufferedInputStream(new FileInputStream(f));
                    while ((readLen = is.read(buf, 0, 1024)) != -1) {
                        zos.write(buf, 0, readLen);
                    }
                    is.close();
                }
            }
        }
        zos.close();
        Logger1.info("压缩完毕!", ZipUtil.class);
    }

    public static void zipStream(InputStream is, OutputStream os, String fileName) throws Exception {
        ZipOutputStream zos = new ZipOutputStream(os);
        ZipEntry ze = null;
        byte[] buf = new byte[1024];
        int readLen = 0;
        ze = new ZipEntry(fileName);
        ze.setTime(System.currentTimeMillis());
        Logger1.info("正在压缩流:" + fileName, ZipUtil.class);
        zos.putNextEntry(ze);
        long total = 0L;
        while ((readLen = is.read(buf, 0, 1024)) != -1) {
            zos.write(buf, 0, readLen);
            total += readLen;
        }
        ze.setSize(total);
        zos.finish();
        zos.close();
        Logger1.info("压缩完毕!", ZipUtil.class);
    }

    public static byte[] unzip(byte[] bs) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ByteArrayInputStream bis = new ByteArrayInputStream(bs);
        bos = new ByteArrayOutputStream();
        Inflater inf = new Inflater();
        InflaterInputStream dis = new InflaterInputStream(bis, inf);
        byte[] buf = new byte[1024];
        try {
            int c;
            while ((c = dis.read(buf)) != -1) {
                bos.write(bs, 0, c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] r = bos.toByteArray();
        return r;
    }

    public static byte[] ungzip(byte[] bs) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ByteArrayInputStream bis = new ByteArrayInputStream(bs);
        bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        try {
            GZIPInputStream gis = new GZIPInputStream(bis);
            int c;
            while ((c = gis.read(buf)) != -1) {
                bos.write(buf, 0, c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] r = bos.toByteArray();
        return r;
    }

    /**
     * 将ZIP文件解压后放入File列表中
     * @param srcFile
     * @param tmpPath
     * @return
     * @throws IOException
     */
    public static List<File> unZipToFile(File srcFile) throws IOException{
        System.out.println(srcFile.getParent());
        String tmpPath = srcFile.getParent();
        ZipFile zipFile = new ZipFile(srcFile);
        Enumeration e = zipFile.getEntries();
        ZipEntry zipEntry = null;
        FileUtil.delete(tmpPath);
        List<File> files = new ArrayList<File>();
        FileUtil.mkdir(tmpPath);
        while(e.hasMoreElements()){
            zipEntry = (ZipEntry)e.nextElement();
            if(zipEntry.isDirectory()){
                FileUtil.mkdir(tmpPath + "/" + zipEntry.getName());
                continue;
            }
            File f = new File(tmpPath + "/" + zipEntry.getName());
             f.getParentFile().mkdirs();
            InputStream in = zipFile.getInputStream(zipEntry);
            OutputStream out = new BufferedOutputStream(new FileOutputStream(f));
            byte[] buf = new byte[1024];
            int c;
            while((c = in.read(buf)) != -1){
                out.write(buf, 0, c);
            }
            files.add(f);
            out.close();
            in.close();
        }
        zipFile.close();
        return files;
    }

    public static boolean unzip(String srcFileName, String destPath) {
        try {
            ZipFile zipFile = new ZipFile(srcFileName);

            Enumeration e = zipFile.getEntries();
            ZipEntry zipEntry = null;
            new File(destPath).mkdirs();
            while (e.hasMoreElements()) {
                zipEntry = (ZipEntry) e.nextElement();
               
                Logger1.info("正在解压" + zipEntry.getName(), ZipUtil.class);
                if (zipEntry.isDirectory()) {
                    new File(destPath + "/" + zipEntry.getName()).mkdirs();
                } else {
                    File f = new File(destPath + "/" + zipEntry.getName());
                    f.getParentFile().mkdirs();

                    InputStream in = zipFile.getInputStream(zipEntry);
                    OutputStream out = new BufferedOutputStream(new FileOutputStream(f));

                    byte[] buf = new byte[1024];
                    int c;
                    while ((c = in.read(buf)) != -1) {
                        out.write(buf, 0, c);
                    }
                    out.close();
                    in.close();
                }
            }
            Logger1.info("解压完毕！",ZipUtil.class);
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
        return true;
    }



    public static boolean unzip(File srcFile,String destPath){
        try {
            ZipFile zipFile = new ZipFile(srcFile);
            Enumeration e = zipFile.getEntries();
            ZipEntry zipEntry = null;
            new File(destPath).mkdirs();
            while (e.hasMoreElements()) {
                zipEntry = (ZipEntry) e.nextElement();
             
                Logger1.info("正在解压 " + zipEntry.getName(),ZipUtil.class);
                if (!(zipEntry.isDirectory())) {
                    String fileName = zipEntry.getName();
                    if (fileName.lastIndexOf("/") != -1) {
                        fileName = fileName.substring(fileName.lastIndexOf("/"));
                    }
                    File f = new File(destPath + "/" + fileName);
                    InputStream in = zipFile.getInputStream(zipEntry);
                    OutputStream out = new BufferedOutputStream(new FileOutputStream(f));

                    byte[] buf = new byte[1024];
                    int c;
                    while ((c = in.read(buf)) != -1) {
                        out.write(buf, 0, c);
                    }
                    out.flush();
                    out.close();
                    in.close();
                }
            }
            zipFile.close();
            Logger1.info("解压完毕！",ZipUtil.class);

        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }

        return true;
    }

    public static boolean unzip(String srcFileName, String destPath, boolean isPath) {
        if (isPath) {
            return unzip(srcFileName, destPath);
        }
        try {
            ZipFile zipFile = new ZipFile(srcFileName);
            Enumeration e = zipFile.getEntries();
            ZipEntry zipEntry = null;
            new File(destPath).mkdirs();
            while (e.hasMoreElements()) {
                zipEntry = (ZipEntry) e.nextElement();
             
                Logger1.info("正在解压 " + zipEntry.getName(),ZipUtil.class);
                if (!(zipEntry.isDirectory())) {
                    String fileName = zipEntry.getName();
                    if (fileName.lastIndexOf("/") != -1) {
                        fileName = fileName.substring(fileName.lastIndexOf("/"));
                    }
                    File f = new File(destPath + "/" + fileName);
                    InputStream in = zipFile.getInputStream(zipEntry);
                    OutputStream out = new BufferedOutputStream(new FileOutputStream(f));

                    byte[] buf = new byte[1024];
                    int c;
                    while ((c = in.read(buf)) != -1) {
                        out.write(buf, 0, c);
                    }
                    out.flush();
                    out.close();
                    in.close();
                }
            }
            zipFile.close();
            Logger1.info("解压完毕！",ZipUtil.class);

        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }

        return true;
    }

    private static List getSubFiles(File baseDir) {
        List ret = new ArrayList();
        ret.add(baseDir);
        if (baseDir.isDirectory()) {
            File[] tmp = baseDir.listFiles();
            for (int i = 0; i < tmp.length; i++) {
                ret.addAll(getSubFiles(tmp[i]));
            }
        }
        return ret;
    }

    private static String getAbsFileName(File baseDir, File realFileName) {
        File real = realFileName;
        File base = baseDir;
        String ret = real.getName();
        if (real.isDirectory()) {
            ret = ret + "/";
        }
        while (real != base) {
            real = real.getParentFile();
            if (real == null) {
                break;
            }
            if (real.equals(base)) {
                ret = real.getName() + "/" + ret;
                break;
            }
            ret = real.getName() + "/" + ret;
        }
        return ret;
    }

    public static void main(String[] args) throws IOException{
        unzip(new File("D:/javadoc.zip").getPath(), "d:/tt");
    }
}
